home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / amiga.free / sorgenti vari / wolf3dmacsource.sit / Wolf3DMacSource / RefSprite.c < prev    next >
C/C++ Source or Header  |  1994-09-20  |  9KB  |  346 lines

  1. #include "WolfDef.h"
  2. #include <string.h>
  3.  
  4. Word *src1,*src2,*dest;        /* Used by the sort */
  5.  
  6. /**********************************
  7.     
  8.     Merges src1/size1 and src2/size2 to dest
  9.     Both Size1 and Size2 MUST be non-zero
  10.     
  11. **********************************/
  12.  
  13. void Merge(Word Size1, Word Size2)
  14. {
  15.     Word *XDest,*XSrc1,*XSrc2;
  16.     
  17. /* merge two parts of the unsorted array to the sorted array */
  18.  
  19.     XDest = dest;
  20.     dest = &XDest[Size1+Size2];
  21.     XSrc1 = src1;
  22.     src1 = &XSrc1[Size1];
  23.     XSrc2 = src2;
  24.     src2 = &XSrc2[Size2];
  25.     
  26.     if (XSrc1[0] < XSrc2[0]) {        /* Which sort to use? */
  27. mergefrom1:
  28.         do {
  29.             XDest[0] = XSrc1[0];    /* Copy one entry */
  30.             ++XDest;
  31.             ++XSrc1;
  32.             if (!--Size1) {            /* Any more? */
  33.                 do {    /* Dump the rest */
  34.                     XDest[0] = XSrc2[0];    /* Copy the rest of data */
  35.                     ++XDest;
  36.                     ++XSrc2;
  37.                 } while (--Size2);
  38.                 return;
  39.             }
  40.         } while (XSrc1[0] < XSrc2[0]);
  41.     }
  42.     do {
  43.         XDest[0] = XSrc2[0];
  44.         ++XDest;
  45.         ++XSrc2;
  46.         if (!--Size2) {
  47.             do {
  48.                 XDest[0] = XSrc1[0];
  49.                 ++XDest;
  50.                 ++XSrc1;
  51.             } while (--Size1);
  52.             return;
  53.         }
  54.     } while (XSrc1[0] >= XSrc2[0]);
  55.     goto mergefrom1;
  56. }
  57.  
  58. /**********************************
  59.     
  60.     Sorts the events from xevents[0] to xevent_p
  61.     firstevent will be set to the first sorted event (either xevents[0] or sortbuffer[0])
  62.     
  63. **********************************/
  64.  
  65. void SortEvents(void)
  66. {
  67.     Word    count;    /* Number of members to sort */
  68.     Word    size;    /* Entry size to sort with */
  69.     Word    sort;    /* Sort count */
  70.     Word    remaining;    /* Temp merge count */
  71.     Word    *sorted,*unsorted,*temp;
  72.     
  73.     count = numvisspr;        /* How many entries are there? */
  74.     if (count<2) {
  75.         firstevent = xevents;    /* Just return the 0 or 1 entries */
  76.         return;                /* Leave now */
  77.     }
  78.     
  79.     size = 1;        /* source size        (<<1 / loop)*/
  80.     sort = 1;        /* iteration number (+1 / loop)*/
  81.     sorted = xevents;
  82.     unsorted = sortbuffer;
  83.     
  84.     do {
  85.         remaining = count>>sort;    /* How many times to try */
  86.         
  87.         /* pointers incremented by the merge */
  88.         src1 = sorted;        /* Sorted array */
  89.         src2 = &sorted[remaining<<(sort-1)];    /* Half point */
  90.         dest = unsorted;    /* Dest array */
  91.         
  92.         /* merge paired blocks*/
  93.         if (remaining) {    /* Any to sort? */
  94.             do {
  95.                 Merge(size,size);    /* All groups equal size */
  96.             } while (--remaining);
  97.         }
  98.         
  99.         /* copy or merge the leftovers */
  100.         remaining = count&((size<<1)-1);    /* Create mask (1 bit higher) */
  101.         if (remaining > size) {    /* one complete block and one fragment */
  102.             src1 = &src2[size];
  103.             Merge(remaining-size,size);
  104.         } else if (remaining) {    /* just a single sorted fragment */
  105.             memcpy(dest,src2,remaining*sizeof(Word));    /* Copy it */
  106.         }
  107.         
  108.         /* get ready to sort back to the other array */
  109.         
  110.         size <<= 1;        /* Double the entry size */
  111.         ++sort;            /* Increase the shift size */
  112.         temp = sorted;    /* Swap the pointers */
  113.         sorted = unsorted;
  114.         unsorted = temp;
  115.     } while (size<count);
  116.     firstevent = sorted;
  117. }
  118.  
  119. /**********************************
  120.     
  121.     Draw a single scaled sprite
  122.     x1 = Left edge, x2 = Right edge, rs_vseg = record for sprite
  123.     
  124. **********************************/
  125.  
  126. void RenderSprite(Word x1,Word x2,vissprite_t *VisPtr)
  127. {
  128.     Word column;
  129.     Word scaler;
  130.         
  131.     scaler = VisPtr->clipscale;        /* Get the size of the sprite */
  132.     column = 0;                    /* Start at the first column */
  133.     if ((int) x1 > VisPtr->x1) {        /* Clip the left? */
  134.         column = (x1-VisPtr->x1)*VisPtr->columnstep;    /* Start here instead */
  135.     }
  136.  
  137. /* calculate and draw each column */
  138.  
  139.     do {
  140.         if (xscale[x1] <= scaler) {    /* Visible? */
  141.             IO_ScaleMaskedColumn(x1,scaler,VisPtr->pos,column>>FRACBITS);
  142.         }
  143.         column+=VisPtr->columnstep;        /* Next column (Fraction) */
  144.     } while (++x1<=x2);
  145. }
  146.  
  147. /**********************************
  148.     
  149.     Add a sprite entry to the render list
  150.     
  151. **********************************/
  152.  
  153. void AddSprite (thing_t *thing,Word actornum)
  154. {
  155.     fixed_t tx;            /* New X coord */
  156.     fixed_t tz;            /* New z coord (Size) */
  157.     Word scale;            /* Scaled size */
  158.     int    px;                /* Center X coord */
  159.     unsigned short *patch;    /* Pointer to sprite data */
  160.     int    x1, x2;            /* Left,Right x */
  161.     Word width;            /* Width of sprite */
  162.     fixed_t trx,try;    /* x,y from the camera */
  163.     vissprite_t *VisPtr;    /* Local pointer to visible sprite record */
  164.  
  165. /* transform the origin point */
  166.     
  167.     if (numvisspr>=(MAXVISSPRITES-1)) {
  168.         return;
  169.     }
  170.     trx = thing->x - viewx;        /* Adjust from the camera view */
  171.     try = viewy - thing->y;        /* Adjust from the camera view */
  172.     tz = R_TransformZ(trx,try);    /* Get the distance */
  173.  
  174.     if (tz < MINZ) {        /* Too close? */
  175.         return;
  176.     }
  177.         
  178.     if (tz>=MAXZ) {        /* Force smallest */
  179.         tz = MAXZ-1;
  180.     }
  181.     scale = scaleatzptr[tz];    /* Get the scale at the z coord */
  182.     tx = R_TransformX(trx,try);    /* Get the screen x coord */
  183.     px = ((tx*(long)scale)>>7) + CENTERX;    /* Use 32 bit precision! */
  184.  
  185. /* calculate edges of the shape */
  186.  
  187.     patch = SpriteArray[thing->sprite];    /* Pointer to the sprite info */
  188.     
  189.     width =((LongWord)patch[0]*scale)>>6;     /* Get the width of the shape */
  190.     if (!width) {
  191.         return;        /* too far away*/
  192.     }
  193.     x1 = px - (width>>1);    /* Get the left edge */
  194.     if (x1 >= (int) SCREENWIDTH) {
  195.         return;        /* off the right side */
  196.     }
  197.     x2 = x1 + width - 1;            /* Get the right edge */
  198.     if (x2 < 0) {
  199.         return;        /* off the left side*/
  200.     }
  201.     VisPtr = &vissprites[numvisspr];
  202.     VisPtr->pos = &patch[0];    /* Sprite info offset */
  203.     VisPtr->x1 = x1;            /* Min x */
  204.     VisPtr->x2 = x2;            /* Max x */
  205.     VisPtr->clipscale = scale;    /* Size to draw */
  206.     VisPtr->columnstep = (patch[0]<<8)/width; /* Step for width scale */
  207.     VisPtr->actornum = actornum;    /* Actor who this is (0 for static) */
  208.  
  209. /* pack the vissprite number into the low 6 bits of the scale for sorting */
  210.  
  211.     xevents[numvisspr] = (scale<<6) | numvisspr;        /* Pass the scale in the upper 10 bits */
  212.     ++numvisspr;        /* 1 more valid record */
  213. }
  214.  
  215. /**********************************
  216.     
  217.     Draw a scaling game over sprite on top of everything
  218.     
  219. **********************************/
  220.  
  221. void DrawTopSprite(void)
  222. {
  223.     unsigned short *patch;
  224.     int x1, x2;
  225.     Word width;
  226.     vissprite_t VisRecord;
  227.  
  228.     if (topspritescale) {        /* Is there a top sprite? */
  229.  
  230. /* calculate edges of the shape */
  231.  
  232.         patch = SpriteArray[topspritenum];        /* Get the info on the shape */
  233.         
  234.         width = (patch[0]*topspritescale)>>7;        /* Adjust the width */
  235.         if (!width) {    
  236.             return;        /* Too far away */
  237.         }
  238.         x1 = CENTERX - (width>>1);        /* Use the center to get the left edge */
  239.         if (x1 >= SCREENWIDTH) {        
  240.             return;        /* off the right side*/
  241.         }
  242.         x2 = x1 + width - 1;        /* Get the right edge */
  243.         if (x2 < 0) {
  244.             return;        /* off the left side*/
  245.         }
  246.         VisRecord.pos = patch;    /* Index to the shape record */
  247.         VisRecord.x1 = x1;            /* Left edge */
  248.         VisRecord.x2 = x2;            /* Right edge */
  249.         VisRecord.clipscale = topspritescale;    /* Size */
  250.         VisRecord.columnstep = (patch[0]<<8)/(x2-x1+1);    /* Width step */
  251.  
  252. /* Make sure it is sorted to be drawn last */
  253.  
  254.         memset(xscale,0,sizeof(xscale));        /* don't clip behind anything */
  255.         if (x1<0) {
  256.             x1 = 0;        /* Clip the left */
  257.         }
  258.         if (x2>=SCREENWIDTH) {
  259.             x2 = SCREENWIDTH-1;    /* Clip the right */
  260.         }
  261.         RenderSprite(x1,x2,&VisRecord);        /* Draw the sprite */
  262.     }
  263. }
  264.  
  265. /**********************************
  266.     
  267.     Draw all the character sprites
  268.     
  269. **********************************/
  270.  
  271. void DrawSprites(void)
  272. {
  273.     vissprite_t    *dseg;        /* Pointer to visible sprite record */
  274.     int x1,x2;                /* Left x, Right x */
  275.     Word i;                    /* Index */
  276.     static_t *stat;            /* Pointer to static sprite record */
  277.     actor_t    *actor;            /* Pointer to active actor record */
  278.     missile_t *MissilePtr;    /* Pointer to active missile record */
  279.     Word *xe;                /* Pointer to sort value */
  280.  
  281.     numvisspr = 0;            /* Init the sprite count */
  282.     
  283. /* add all sprites in visareas*/
  284.  
  285.     if (numstatics) {        /* Any statics? */
  286.         i = numstatics;
  287.         stat = statics;            /* Init my pointer */
  288.         do {
  289.             if (areavis[stat->areanumber]) {    /* Is it in a visible area? */
  290.                 AddSprite((thing_t *) stat,0);    /* Add to my list */
  291.             }
  292.             ++stat;        /* Next index */
  293.         } while (--i);    /* Count down */
  294.     }
  295.     
  296.     if (numactors>1) {        /* Any actors? */
  297.         i = 1;                /* Index to the first NON-PLAYER actor */
  298.         actor = &actors[1];    /* Init pointer */
  299.         do {
  300.             if (areavis[actor->areanumber]) {    /* Visible? */
  301.                 AddSprite ((thing_t *)actor, i);    /* Add it */
  302.             }
  303.             ++actor;        /* Next actor */
  304.         } while (++i<numactors);    /* Count up */
  305.     }
  306.     
  307.     if (nummissiles) {        /* Any missiles? */
  308.         i = nummissiles;    /* Get the missile count */
  309.         MissilePtr = missiles;    /* Get the pointer to the first missile */
  310.         do {
  311.             if (areavis[MissilePtr->areanumber]) {    /* Visible? */
  312.                 AddSprite((thing_t *)MissilePtr,0);    /* Show it */
  313.             }
  314.             ++MissilePtr;    /* Next missile */
  315.         } while (--i);        /* Count down */
  316.     }
  317.  
  318.     i = numvisspr;
  319.     if (i) {            /* Any sprites? */
  320.  
  321. /* sort sprites from back to front*/
  322.  
  323.         SortEvents();
  324.  
  325. /* draw from smallest scale to largest */
  326.  
  327.         xe=firstevent;
  328.         do {
  329.             dseg = &vissprites[xe[0]&(MAXVISSPRITES-1)];    /* Which one? */
  330.             x1 = dseg->x1;
  331.             if (x1<0) {        /* Clip the left? */
  332.                 x1 = 0;
  333.             }
  334.             x2 = dseg->x2;
  335.             if (x2>= (int)SCREENWIDTH) {    /* Clip the right? */
  336.                 x2 = SCREENWIDTH-1;
  337.             }
  338.             RenderSprite(x1,x2,dseg);    /* Draw the sprite */
  339.             ++xe;
  340.         } while (--i);
  341.     }
  342. }
  343.  
  344.  
  345.  
  346.